#!/usr/bin/env python
# coding=utf-8

if __name__ == '__main__':
    """ for file debug"""
    import sys,os
    sys.path.insert(0,os.path.join( os.getcwd(), '..' ))

__author__ = 'vavava'

from vavava import util
from vavava.dispatcher import Dispatcher
from vavava.workshop import WorkShop
from taskserver_interface import ServerInterface
from taskserver_config import TaskServerConfig,TaskServerLog
import time
from sys import argv
from vavava.dbworkshop import DBWorkshop
from DBUtils import PooledDB
import MySQLdb

def usage():
    print ( """tracker [-d debug_level][-t timeout][-ids id[|id]]""")

def init_config(TEST=False):
    argv_dic=util.parse_argvs(argv)
    config=TaskServerConfig()

    if TEST:
        config.load("test_task_server.conf")
    elif argv_dic and argv_dic.get('-config'):
        config.load(argv_dic.get('-config'))
    else:
        config.load('task_server-test.conf')

    log= TaskServerLog.get_logger(config)

    if argv_dic:
        if argv_dic.get('-d'):    config.debug_level=int(argv_dic.get('-d'))
        if argv_dic.get('-t'):    config.sock_timeout=float(argv_dic.get('-t'))
        #if argv_dic.get('-ids'):  config.userTokens=argv_dic.get('-ids').split('|')

    return config,log

def init_workshops(config,log):
    type1=type2=0
    workshops = {}
    for group in config.groups:
        try:
            dbpool=None
            if group.db_support:
                dbpool = _get_dbpool(
                    minsize = group.db_pool_min,
                    maxsize = group.db_pool_max,
                    host    = group.host,
                    port    = group.port,
                    user    = group.user,
                    passwd  = group.password,
                    db      = group.db,
                    charset = group.charset
                )
                workshops[group.group_id] = DBWorkshop(
                    dbpool=dbpool,
                    group="",
                    maxsize=None,
                    minsize=group.work_queue_size,
                    redoable_supoort=group.redoable_supoort,
                    priority_support=group.priority_support,
                    log=log,
                    parent=None
                )
                log.info("add workshop to dispatcher(db):%s"%group.group_id)
                type1 += 1
            else:
                workshops[group.group_id] = WorkShop(
                    group=group.group_id,
                    maxsize=None,
                    minsize=group.work_queue_size,
                    redoable_supoort=group.redoable_supoort,
                    priority_support=group.priority_support,
                    log=log,
                    parent=None
                )
                log.info("add workshop to dispatcher:%s"%group.group_id)
                type2 += 1
        except Exception as e:
            log.exception(e)

        log.info("Dispatcher:workshop(%d);dbworkshop(%d)"%(type1,type2)) #???????
    return workshops

def serve():
    config,log = init_config()
    display_str="""Tracking Begin[%s]: Debug level=%d Socket timeout=%f """
    log.info(display_str%(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())),
                          config.debug_level,config.sock_timeout))
    try:
        # 开始工作 ===============================================================

        workshops = init_workshops(config,log)

        dsp = Dispatcher( workshops=workshops, name="dispatcher", log=log )
        server = ServerInterface(processor=dsp,host=config.listen_ip,
            port=config.listen_port, log=log )

        log.info("启动分配器")
        for group in config.groups:
            if group.auto_start:
                dsp.ActivateWorkshop(group.group_id)

        log.info("启动监听服务器")
        #server.StartServer()

        # ??? 添加默认工作
        add_autostart_works(dsp,log,config,config.works)

        # 工作完成 ===============================================================

        while True:
            if config.debug_level == 1:
                dsp.GetInfo()
            time.sleep(3)

        log.info('main thread(%s):stop'%
                 time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())))
        dsp.DeactivateAllWorkshops()
        #server.StopServer()
        log.info('main thread(%s):stopped'%
                 time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())))
    except(KeyboardInterrupt):
        print('main thread(%f): User canceled by Ctrl-c'%time.clock())
    finally:
        print('main thread(%f):stop'%time.clock())
        if dsp:
            dsp.DeactivateAllWorkshops()
        #if server:
        #    server.StopServer()
        log.info('main thread(%s):stopped'%
              time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())))

def _get_dbpool(minsize=10,maxsize=20,host='localhost',
               port=55555,user='root',passwd='root',db='test',charset='utf8'):
    dbpool = PooledDB.PooledDB(
        creator=MySQLdb,
        mincached=minsize,
        maxcached=maxsize,
        maxshared=minsize,
        maxconnections=100,
        blocking=False,
        host=host,
        #port=port,
        user=user,
        passwd=passwd,
        db=db,
        charset=charset
    )
    return dbpool

def add_autostart_works(dsp,log,config,works):
    try:
        code = ""
        for work in works:
            if not work.auto_start:
                continue

            code = ""
            if work.type_path != "":
                code += "import %s\n"%work.type_path
                code += "work = %s.%s ("%(work.type_path,work.type_name)
            else:
                code += "work = %s ("%work.type_name
            if work.begin_time:
                code += "begin_time=%f,"%work._begin_time
            if work.period:
                code += "period=%f,"%work.period
            if work.group_id:
                code += "group='%s',"%work.group_id
            if work.awarg and work.awarg != "":
                code += "%s," % work.awarg
            code +=  "log=log )\n"
            code += "dsp.AddWork(work)\n"

            log.info("execute:\n%s"%code)

            obj = compile(code,'','exec')

            exec(obj)
    except Exception as e:
        log.error("error on add work to dispatcher:")
        log.exception(e)

if __name__ == '__main__':
    serve()


